

#include "discretizador.h"

#include "coord.h"
#include "superficie.h"
#include "curva.h"
#include "vertexs.h"

#include <GL/glut.h>




void Discretizador::franjaTrianStrip(float u, float pasoU) const {
   float u_mas_du = u + pasoU;

   discr->grupo(GL_TRIANGLE_STRIP);

   for(float v = 0; v < 1.0; v += pasoDiscretizacionV) {
      parVertices(u, u_mas_du, v);
   }

   /* Forzamos que el ultimo par este asociado al paso de discretizacion 1.0 final*/
   parVertices(u, u_mas_du, 1.0);

}

void Discretizador::parVertices(float u_p, float u_q, float v) const {
   discr->vertex(u_p, v, sup->normal(u_p, v), sup->eval(u_p, v));
   discr->vertex(u_q, v, sup->normal(u_q, v), sup->eval(u_q, v));
}



Vertexs* Discretizador::superficie(const Superficie &sup) const {
   this->sup = &sup;
   this->discr.reset(new Vertexs());

   float ultimo = 0.0;

   for(float u = 0.0; u < 1.0 - pasoDiscretizacionU; u += pasoDiscretizacionU){
      franjaTrianStrip(u, pasoDiscretizacionU);
      ultimo = u + pasoDiscretizacionU;
   }

   if(ultimo < 1.0) {
      // Forzamos que la ultima franja discretizada cierre a 1.0
      franjaTrianStrip(ultimo, 1.0 - ultimo);
   }

   this->discr->cerrar();
   return this->discr.release();
}

Vertexs* Discretizador::curvaRellena(const Curva &curva) const {
   return curvaRellena(curva, Coord(0, 0, 1));
}

Vertexs* Discretizador::curvaRellena(const Curva &curva, const Coord &normal) const {
   discr.reset(new Vertexs());

   discr->grupo(GL_TRIANGLE_FAN);

   discr->vertex(0.5, 0.5, normal, curva.centro());

   for(float u = 0.0; u < 0.25; u += pasoDiscretizacionU) {
      discr->vertex(0, u*4, normal, curva(u));
   } 
   for(float u = 0.25; u < 0.5; u += pasoDiscretizacionU) {
      discr->vertex( (u - 0.25) * 4, 1, normal, curva(u));
   } 
   for(float u = 0.5; u < 0.75; u += pasoDiscretizacionU) {
      discr->vertex( 1, 1 - ((u - 0.5) * 4), normal, curva(u));
   } 
   for(float u = 0.75; u < 1.0; u += pasoDiscretizacionU) {
      discr->vertex( 1 - ((u - 0.75) * 4), 0, normal, curva(u));
   } 

   discr->vertex(0, 0, normal, curva(1.0));

   discr->cerrar();
   return discr.release();
}


Vertexs* Discretizador::entreCurvas(const Curva &curva, const Curva &otraCurva,
      const Coord &normal) const {
   discr.reset(new Vertexs());
   discr->grupo(GL_TRIANGLE_STRIP);

   float u = 0.0;
   for(; u < 1.0; u += pasoDiscretizacionU) {
      discr->vertex(u, 1.0, normal, otraCurva.eval(u));
      discr->vertex(u, 0.0, normal, curva.eval(u));
   }

   discr->vertex(1.0, 1.0, normal, otraCurva.eval(1.0));
   discr->vertex(1.0, 0.0, normal, curva.eval(1.0));
   
   discr->cerrar();
   return discr.release();
}
